/**
 * AGNParameterHandle.java
 */
package agngui.agnmodel;
import javax.vecmath.Point2i;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;

/**
 * Describes a handle attached to a parameter describing a piece of
 * geometry.
 */
public abstract class AGNParameterHandle {
	/**
	 * flag signifying that this is a Linear Parameter Handle
	 */
    public static final int TYPE_LINEAR     = 1;
    
    /**
     * flag signifying that this is an Angular Parameter Handle
     */
    public static final int TYPE_ANGULAR    = 2;
    
    /**
     * flag signifying that this is a Rotational Parameter Handle
     */
    public static final int TYPE_ROTATIONAL = 3;

    /**
     * This handle's type
     */
    private int    type = 0;
    
    /**
     * The name of the parameter which this handle affects
     */
	private String identifier;

	/**
	 * the point in world space that this handle is centered upon
	 */
    protected Point3d   point;
    
    /**
     * the axis upon which this handle is drawn
     */
    protected Vector3d  axis;
    
    /**
     * The object that this handle affects
     */
    protected AGNObject object;
    
    /**
     * The value that this handle takes
     */
    protected double    recentValue;

    /**
     * AGNParameterHandle
     *
     * Initializes the parameter handle.
     * 
     * @param type   The type of parameter this object represents.
     * @param object The object this handle belongs to
     * @param point  The location of this handle in world space
     * @param axis   The axis of interest (significance depends on subclass)
     */
    public AGNParameterHandle( int type, AGNObject object, Point3d point, Vector3d axis, String identifier ) {
        this.type       = type;
        this.object     = object;
        this.point      = point;
		this.identifier = identifier;
        this.axis       = axis;
    }

    /**
     * isClickedOn
     *
     * @param mX The x-coordinate of the mouse click
     * @param mY The y-coordinate of the mouse click
     * @param canvas The AGNModelCanvas object responsible for rendering the HUD
     * @return True if the mouse coordinates intersect with this guy, false otherwise
     */
    public boolean isClickedOn( int mX, int mY, AGNModelCanvas canvas ) {
        boolean retVal;
        Point2i screenPoint = canvas.getScreenLocationFromWorldSpace( new Point3d( point ) );   

        int maxX = screenPoint.x + (AGNModelCanvas.RECT_WIDTH  / 2);
        int minX = screenPoint.x - (AGNModelCanvas.RECT_WIDTH  / 2);
        int maxY = screenPoint.y + (AGNModelCanvas.RECT_HEIGHT / 2);
        int minY = screenPoint.y - (AGNModelCanvas.RECT_HEIGHT / 2);

        retVal = ((mX <= maxX) && (mX >= minX)) && ((mY <= maxY) && (mY >= minY)); 

        return retVal;
    }

    /**
     * calculateNewValueFromWorldLocation
     *
     * Calculates the new handle value based on the world point passed, and
     * stores the most recent value internally.
     *
     * @param worldPoint The point in world space projected by
     *                   projectClickOntoControlAxis
     * @return The calculated value (depends on handle type)
     */
    public abstract double calculateNewValueFromWorldLocation( Point3d worldPoint );

    /**
     * projectClickOntoControlAxis
     *
     * Projects a mouse click onto the actual control axis in world space and   
     * gets that world-space intersection point.
     *
     * @param mX The mouse click x-coordinate
     * @param mY The mouse click y-coordinate
     * @param renderer The model renderer, needed for camera access and projection
     * @return The point in world-space of the finally projected point.
     */
    public abstract Point3d projectClickOntoControlAxis( int mX, int mY, AGNModelRenderer renderer );

    /** 
     * getType
     *
     * Get this handle's handle type.
     *
     * @return this handle's handle type.
     */
    public int getType() {
        return type;
    } 

    /**
     * getPoint
     *
     * Get this handle's point.
     *
     * @return a reference to this handle's point
     */
    public Point3d getPoint() {
        return point;
    }

    /**
     * getAxis
     *
     * Get this handle's main axis.
     *
     * @return a reference to this handle's main axis
     */
    public Vector3d getAxis() {
        return axis;
    }   
	
    /**
     * getIdentifier
     *
     * Get this handle's identifier string.
     *
     * @return a reference to this handle's identifier string.
     */
	public String getIdentifier() {
		return identifier;
	}

    /**
     * getObject
     *
     * Gets this handle's parent object reference.
     *
     * @return a reference to this handle's parent object.
     */
    public AGNObject getObject() {
        return object;
    }   

    /**
     * getRecentValue
     *
     * Gets this handle's recent value.
     *
     * @return this handle's recent value
     */
    public double getRecentValue() {
        return recentValue;
    }

    /**
     * setPoint
     *
     * Sets this handle's point.
     *
     * @param point This handle's new point
     */
    public void setPoint( Point3d point ) {
        this.point = point;
    }

    /**
     * setRecentValue
     *
     * Sets this handle's recent value.
     *
     * @param newRecentValue this handle's recent value
     */
    public void setRecentValue( double newRecentValue ) {
        recentValue = newRecentValue;
    }
}
